package chagine.core.util;

import chagine.core.ErrorCode;
import chagine.core.exception.SeeingException;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.LocalDateTimeUtil;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

public class DateUtil {

    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter DATE_TIME_NO_SECOND_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    public static final DateTimeFormatter SHORT_TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
    public static final DateTimeFormatter SIMPLE_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("MM/dd HH:mm");


    /**
     * 将时间戳转换为对象
     *
     * @param timestamp 时间戳(秒)
     */
    public static LocalDateTime getLocalDateTimeByTimestamp(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp * 1000L), ZoneOffset.of("+8"));
    }

    public static LocalDateTime getLocalDateTimeByTimestampMills(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.of("+8"));
    }

    /**
     * 根据时间戳，获得当天起始时间
     *
     * @return 时间戳对象
     */
    public static LocalDateTime getDayStart(LocalDateTime localDateTime) {
        return localDateTime.with(LocalTime.MIN);
    }

    /**
     * 根据时间戳(秒)，获得当天起始时间
     *
     * @return 时间戳对象
     */
    public static LocalDateTime getDayStart(long timestamp) {
        LocalDateTime localDateTime = getLocalDateTimeByTimestamp(timestamp);
        return getDayStart(localDateTime);
    }

    /**
     * 根据时间戳(秒)，获得当天起始时间
     *
     * @return 时间戳对象
     */
    public static LocalDateTime getDayStart(String date) {
        LocalDateTime localDateTime = getLocalDateTimeByDateOrDateTime(date);
        return getDayStart(localDateTime);
    }

    /**
     * 根据时间戳(秒)，获得当天起始时间戳
     *
     * @return 单位秒
     */
    public static long getDayStartTimestamp(long timestamp) {
        LocalDateTime dayStart = getDayStart(timestamp);
        return getTimestampFromLocalDateTime(dayStart);
    }

    /**
     * 根据时间戳，获得当天起始时间戳
     *
     * @return 单位秒
     */
    public static long getDayStartTimestamp(LocalDateTime localDateTime) {
        LocalDateTime dayStart = getDayStart(localDateTime);
        return getTimestampFromLocalDateTime(dayStart);
    }

    /**
     * 根据时间戳(秒)，获得当天结束时间
     *
     * @return 时间戳对象
     */
    public static LocalDateTime getDayEnd(String date) {
        LocalDateTime localDateTime = getLocalDateTimeByDateOrDateTime(date);
        return getDayEnd(localDateTime);
    }

    /**
     * 根据时间戳(秒)，获得当天结束时间
     *
     * @return 时间戳对象
     */
    public static LocalDateTime getDayEnd(long timestamp) {
        LocalDateTime localDateTime = getLocalDateTimeByTimestamp(timestamp);
        return getDayEnd(localDateTime);
    }

    /**
     * 根据时间戳，获得当天结束时间
     *
     * @return 时间戳对象
     */
    public static LocalDateTime getDayEnd(LocalDateTime localDateTime) {
        return localDateTime.with(LocalTime.MAX);
    }

    /**
     * 根据时间戳(秒)，获得当天结束时间戳
     *
     * @return 单位秒
     */
    public static long getDayEndTimestamp(long timestamp) {
        LocalDateTime dayEnd = getDayEnd(timestamp);
        return getTimestampFromLocalDateTime(dayEnd);
    }

    /**
     * 根据时间戳，获得当天结束时间戳
     *
     * @return 单位秒
     */
    public static long getDayEndTimestamp(LocalDateTime localDateTime) {
        LocalDateTime dayEnd = getDayEnd(localDateTime);
        return getTimestampFromLocalDateTime(dayEnd);
    }

    /**
     * 将时间对象转换为时间戳(秒)
     */
    public static long getTimestampFromLocalDateTime(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
    }

    /**
     * 根据秒级时间戳获得年份
     *
     * @param timestamp 时间戳(秒)
     */
    public static int getYearNumberByTimestamp(long timestamp) {
        LocalDateTime time = getLocalDateTimeByTimestamp(timestamp);
        return time.getYear();
    }

    /**
     * 时间戳格式化为年月日, yyyy-MM-dd HH:mm:ss
     *
     * @param timestamp 时间戳(秒)
     */
    public static String getDateTimeFormatter(Long timestamp) {
        if (timestamp == null) {
            return null;
        }
        LocalDateTime time = getLocalDateTimeByTimestamp(timestamp);
        return getDateTimeFormatter(time);
    }

    /**
     * 时间戳格式化为年月日, yyyy-MM-dd HH:mm:ss
     *
     * @param timestamp 时间戳(秒)
     */
    public static String getDateTimeFormatter(LocalDateTime timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.format(DATE_TIME_FORMATTER);
    }

    /**
     * 时间戳格式化为年月日, yyyy-MM-dd HH:mm
     *
     * @param timestamp 时间戳(秒)
     */
    public static String getDateShortTimeFormatter(Long timestamp) {
        if (timestamp == null) {
            return null;
        }
        LocalDateTime time = getLocalDateTimeByTimestamp(timestamp);
        return getDateShortTimeFormatter(time);
    }

    /**
     * 时间戳格式化为年月日, yyyy-MM-dd HH:mm
     *
     * @param timestamp 时间戳(秒)
     */
    public static String getDateShortTimeFormatter(LocalDateTime timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.format(DATE_TIME_NO_SECOND_FORMATTER);
    }

    /**
     * 时间戳格式化为年月日, yyyy-MM-dd
     *
     * @param timestamp 时间戳(秒)
     */
    public static String getDateFormatter(Long timestamp) {
        if (timestamp == null) {
            return null;
        }
        LocalDateTime time = getLocalDateTimeByTimestamp(timestamp);
        return getDateFormatter(time);
    }

    /**
     * 时间戳格式化为 HH:mm
     * @param timestamp 时间戳(秒)
     */
    public static String getSimpleShortTimeFormatter(LocalDateTime timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.format(SHORT_TIME_FORMATTER);
    }

    /**
     * 时间戳格式化为年月日, HH:mm
     * @param timestamp 时间戳(秒)
     */
    public static String getSimpleDateTimeFormatter(LocalDateTime timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.format(SIMPLE_DATE_TIME_FORMATTER);
    }

    /**
     * 时间戳格式化为年月日, yyyy-MM-dd
     *
     * @param timestamp 时间戳(秒)
     */
    public static String getDateFormatter(LocalDateTime timestamp) {
        if (timestamp == null) {
            return null;
        }
        return timestamp.format(DATE_FORMATTER);
    }

    /**
     * 将格式化后的时间，转换为时间戳
     * 支持 yyyy-MM-dd, 与 yyyy-MM-dd HH:mm:ss
     */
    public static Long getTimestampByDateOrDateTime(String formatterDate) {
        LocalDateTime dateTime = getLocalDateTimeByDateOrDateTime(formatterDate);
        return dateTime != null ? getTimestampFromLocalDateTime(dateTime) : null;
    }

    /**
     * 将格式化后的时间，转换为时间戳
     * 支持 yyyy-MM-dd, 与 yyyy-MM-dd HH:mm:ss
     */
    public static LocalDateTime getLocalDateTimeByDateOrDateTime(String formatterDate) {
        LocalDateTime dateTime = null;
        try {
            dateTime = LocalDateTime.parse(formatterDate, DATE_TIME_FORMATTER);
        } catch (Exception ignore) {
        }
        if (dateTime == null) {
            try {
                LocalDate date = LocalDate.parse(formatterDate, DATE_TIME_NO_SECOND_FORMATTER);
                dateTime = date.atStartOfDay();
            } catch (Exception ignore) {
            }
        }
        if (dateTime == null) {
            try {
                LocalDate date = LocalDate.parse(formatterDate, DATE_FORMATTER);
                dateTime = date.atStartOfDay();
            } catch (Exception ignore) {
            }
        }
        return dateTime;
    }

    /**
     * 通过出生日期计算年龄，单位岁
     */
    public static Integer getAge(Long birthdayTime) {
        if (birthdayTime == null) {
            return null;
        }
        try {
            LocalDate birthdayDate = getLocalDateTimeByTimestamp(birthdayTime).toLocalDate();
            LocalDate nowDate = LocalDate.now();
            if (birthdayDate.isAfter(nowDate)) {
                return null;
            }
            int years = birthdayDate.until(nowDate).getYears();
            return years < 0 ? -1 : years;
        } catch (Exception e) {
            return -1;
        }
    }

    /**
     * 通过出生日期计算年龄，单位岁
     */
    public static Integer getAge(LocalDate birthdayDate) {
        if (birthdayDate == null) {
            return null;
        }
        try {
            LocalDate nowDate = LocalDate.now();
            if (birthdayDate.isAfter(nowDate)) {
                return null;
            }
            int years = birthdayDate.until(nowDate).getYears();
            return years < 0 ? -1 : years;
        } catch (Exception e) {
            return -1;
        }
    }

    public static String getAgeLessThan3Year(LocalDate birthdayDate, boolean throwError) {
        if (birthdayDate == null) {
            return null;
        }
        LocalDate nowDate = LocalDate.now();
        if (birthdayDate.isAfter(nowDate)) {
            Assert.error(throwError, ErrorCode.BUSINESS_EXCEPTION, "出生年月不能超过当前日期");
            return null;
        }
        StringBuilder sb = new StringBuilder();
        int age = birthdayDate.until(nowDate).getYears();
        if (age >= 3) {
            sb.append(age).append("岁");
            // 大于3周岁
            return sb.toString();
        } else if (age >= 1) {
            long monthsV = birthdayDate.until(nowDate, ChronoUnit.MONTHS);
            int month = ((int) monthsV) % 12;
            sb.append(age).append("岁");
            if (month != 0) {
                sb.append(month).append("个月");
            }
            return sb.toString();
        } else {
            // 小于1周岁
            long monthsV = birthdayDate.until(nowDate, ChronoUnit.MONTHS);
            int days = birthdayDate.until(nowDate).getDays();
            if (monthsV != 0) {
                sb.append(monthsV).append("个月");
            }
            if (days != 0 || monthsV == 0) {
                sb.append(days).append("天");
            }
            return sb.toString();
        }
    }

    /**
     * 通过出生日期计算年龄
     * 小于1周岁，单位：X月X天
     * 1周岁到3周岁，单位：X岁X周
     * 3周岁以上，单位：X岁
     */
    public static String getAgeLessThan3Year(LocalDate birthdayDate) {
        return getAgeLessThan3Year(birthdayDate, false);
    }

    /**
     * 通过出生日期计算年龄
     * 小于1周岁，单位：X月X天
     * 1周岁到3周岁，单位：X岁X周
     * 3周岁以上，单位：X岁
     */
    public static String getAgeLessThan3Year(Long birthdayTime, boolean throwError) {
        if (birthdayTime == null) {
            return null;
        }
        LocalDate birthdayDate = getLocalDateTimeByTimestamp(birthdayTime).toLocalDate();
        return getAgeLessThan3Year(birthdayDate, throwError);
    }

    /**
     * 通过出生日期计算年龄
     * 小于1周岁，单位：X月X天
     * 1周岁到3周岁，单位：X岁X周
     * 3周岁以上，单位：X岁
     */
    public static String getAgeLessThan3Year(Long birthdayTime) {
        return getAgeLessThan3Year(birthdayTime, false);
    }

    public static Long getTimeFromFunvbj(String date) {
        if (!StringUtils.hasText(date)) {
            return null;
        }
        date = date.trim();
        DateTime dateTime = cn.hutool.core.date.DateUtil.parse(date, "MM/dd/yyyy hh:mm:ss", "MM/dd/yyyy");
        return dateTime.getTime() / 1000;
    }

    public static LocalDateTime getLocalDateTimeFromFunvbj(String date) {
        Long timestamp = getTimeFromFunvbj(date);
        if (timestamp == null) {
            return null;
        }
        return getLocalDateTimeByTimestamp(timestamp);
    }

    /**
     * 日期的long类型转为string类型
     */
    public static String getShortTimeStr(Long timestamp) throws SeeingException {
        if (timestamp == null) {
            return null;
        }
        LocalDateTime time = getLocalDateTimeByTimestamp(timestamp);
        return time.format(SHORT_TIME_FORMATTER);
    }

    /**
     * 截取生日  yyyy-mm-dd
     */
    public static String getBirthday(String idNumber) {
        if (idNumber.length() != 18 && idNumber.length() != 15) {
            return null;
//            Assert.error(true, ErrorCode.BUSINESS_EXCEPTION, "身份证号码不正确");
        }
        String birthday = "";

        if (idNumber.length() == 18) {
            String year = idNumber.substring(6).substring(0, 4);// 得到年份
            String month = idNumber.substring(10).substring(0, 2);// 得到月份
            String day = idNumber.substring(12).substring(0, 2);// 得到日
            birthday = year + "-" + month + "-" + day;
        } else if (idNumber.length() == 15) {
            String year = "19" + idNumber.substring(6, 8);// 年份
            String month = idNumber.substring(8, 10);// 月份
            String day = idNumber.substring(10, 12);// 得到日
            birthday = year + "-" + month + "-" + day;
        }

        return birthday;
    }

    public static LocalDate getLocaldateBirthday(String idNumber) {
        return LocalDateTimeUtil.parseDate(DateUtil.getBirthday(idNumber));
    }



    /**
     * 日期的string类型转为long类型
     *
     * @param
     * @return
     */
    public static Long getDateLong(String date, Integer unit) throws SeeingException {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(date).getTime() / unit;
        } catch (Exception ex) {
            throw new SeeingException(ErrorCode.RUNNING_EXCEPTION, "日期转换异常");
        }

    }


    /**
     * 获取今日时间
     * @author zevin
     */
    public static String getToday(){
        return LocalDateTime.now().format(DATE_TIME_FORMATTER);
    }


    public static void main(String[] args) {
//        LocalDateTime localDateTimeFromFunvbj = getLocalDateTimeFromFunvbj("02/19/2022 00:00:00");
        LocalDateTime localDateTime = getLocalDateTimeByDateOrDateTime("2022-01-01 12:13");
        System.out.println("localDateTime = " + localDateTime);
    }



    /**
     * 格式化中文提示（XX前）
     * @param timestamp 时间戳(秒)
     */
    public static String formatTimeTip(Long timestamp) {
        if(timestamp == null){
            return null;
        }
        long seconds = (System.currentTimeMillis()/1000 - timestamp);
        if (seconds < 2592000) {
            // 小于30天如下显示
            if (seconds >= 86400) {
                return Long.toString(seconds / 86400) + " 天前";
            } else if (seconds >= 3600) {
                return Long.toString(seconds / 3600) + " 小时前";
            } else if (seconds >= 60) {
                return Long.toString(seconds / 60) + " 分钟前";
            } /*else if (seconds < 0) {
                return "刚刚";
            } else {
                return Long.toString(seconds + 1) + " " + "秒前";
            }*/ else{
                return "刚刚";
            }
        } else {
            // 大于30天直接显示日期
            Date nowTime = new Date(timestamp * 1000);
            String format = DateFormat.getDateInstance().format(nowTime);
            if(format.contains("2020")){
                return format.substring(5,format.length());
            }else{
                return DateFormat.getDateInstance().format(nowTime);

            }
        }
    }
}
